home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Graphics⁄Sound / Contours source / fractal2.c < prev   
Text File  |  1985-09-03  |  7KB  |  282 lines

  1.  
  2. /*
  3. ' 3-Dimensional Fractal surface generating program
  4. ' From July '85 Creative Computing.
  5. */
  6.  
  7. #include <quickdraw.h>
  8. #include <toolutil.h>
  9. #define watchCursor 4    /* Should be in TOOLUTIL.H but isn't.  JEC */
  10. double ran();        /* Should be in MATH.H but isn't.  JEC */
  11.  
  12. #include "fractal.h"
  13.  
  14. #define TRUE (-1)
  15. #define FALSE 0
  16.  
  17. int linestart;        /* True at the first of the line. */
  18. int color;        /* True when plotting land, else false. */
  19.  
  20. calcsurf(level)
  21. int level;
  22. {
  23.     int i, j, length, incrby, sk;
  24.     float power;
  25.     CursHandle ticktock;
  26.     
  27.     if (!points)
  28.         return;
  29.     ticktock = GetCursor(watchCursor);
  30.     if (ticktock)
  31.         SetCursor(*ticktock);    /* Show watch (wait) */
  32.  
  33.     xmax = 1 << level;
  34.     ymax = xmax/2;
  35.     for (i=0; i<=xmax; i++)        /* Clear the Array.  Use i & incrby as temps. */
  36.         for (incrby=0; incrby<=ymax; incrby++)
  37.             (*points)[i][incrby] = 0;
  38.  
  39.     for (i=1; i<= level; i++) {
  40.         for (power=1.0, j=0; j<i; j++)
  41.             power *= 1.8;
  42.         length = 10000/power;        /* = 10000/(1.8^i) */
  43.         incrby = xmax/(1 << i);      /* # of line segments in a side of the triangle. */
  44.         sk = incrby * 2;
  45.         calcxs(length, incrby, sk);
  46.         calcys(length, incrby, sk);
  47.         calcdiags(length, incrby, sk);
  48.     }
  49.     InitCursor();        /* Put back the arrow. */
  50. }
  51.  
  52. calcxs(len, incr, sk)    /* Assign heights along x in array. */
  53. int len;
  54. register int incr, sk;
  55. {
  56.     register int y, x;
  57.     int d1, d2;
  58.  
  59.     for (y=0; y < xmax; y += sk) {
  60.         for (x = incr+y; x <= xmax; x += sk) {
  61.             d1 = getdata(x-incr, y);
  62.             d2 = getdata(x+incr, y);
  63.             stuffdata(((d1+d2)>>1) + (int)(ran()*(len>>1)) - (len>>2), x, y);
  64.         }
  65.     }
  66. }
  67.  
  68. calcys(len, incr, sk)    /* Assign heights along y in array. */
  69. int len;
  70. register int incr, sk;
  71. {
  72.     register int y, x;
  73.     int d1, d2;
  74.     
  75.     for (x=xmax; x >= 1; x -= sk)
  76.         for (y = incr; y <= x; y += sk) {
  77.             d1 = getdata(x, y+incr);
  78.             d2 = getdata(x, y-incr);
  79.             stuffdata(((d1+d2)>>1) + (int)(ran()*(len>>1)) - (len>>2), x, y);
  80.         }
  81. }
  82.  
  83. calcdiags(len, incr, sk)    /* Assign heights along diagonal in array. */
  84. int len;
  85. register int incr, sk;
  86. {
  87.     register int y, x;
  88.     int d1, d2;
  89.     
  90.     for (x=0; x < xmax; x += sk)
  91.         for (y = incr; y <= xmax-x; y += sk) {
  92.             d1 = getdata(x+y-incr, y-incr);
  93.             d2 = getdata(x+y+incr, y+incr);
  94.             stuffdata(((d1+d2)>>1) + (int)(ran()*(len>>1)) - (len>>2), x+y, y);
  95.         }
  96. }
  97.  
  98. getdata(x, y)
  99. register int x, y;
  100. {
  101.     if (y <= ymax)
  102.         return (*points)[x][y];
  103.     else
  104.         return (*points)[xmax-x][xmax+1-y];
  105. }
  106.  
  107. stuffdata(d, x, y)
  108. register int d, x, y;
  109. {
  110.     if (y <= ymax)
  111.         (*points)[x][y] = d;
  112.     else
  113.         (*points)[xmax-x][xmax+1-y] = d;
  114. }
  115.  
  116.  
  117. /*
  118. **    Our window is already open at this point, and it is cleared,
  119. **    all we have to do now is fill it.
  120. **    Draw the 2D projection of the triangular database on the screen.
  121. */
  122.  
  123. plotdata()
  124. {
  125.     register int xindex, yindex;
  126.     
  127.     if (!points)
  128.         return;
  129.     color = TRUE;        /* On land to start. */
  130.  
  131.     for (xindex=0; xindex<=xmax; xindex++) {    /* Plot along X axis. */
  132.         linestart = TRUE;
  133.         for (yindex=0; yindex<=xindex; yindex++)
  134.             doplot(xindex, yindex);
  135.     }
  136.     for (yindex=0; yindex<=xmax; yindex++) {    /* Plot along Y axis. */
  137.         linestart = TRUE;
  138.         for (xindex=yindex; xindex<=xmax; xindex++)
  139.             doplot(xindex, yindex);
  140.     }
  141.     for (xindex=0; xindex<=xmax; xindex++) {    /* Plot along the diagonal. */
  142.         linestart = TRUE;
  143.         for (yindex=0; yindex<=xmax-xindex; yindex++)
  144.             doplot(xindex+yindex, yindex);
  145.     }
  146. }
  147.  
  148. doplot(xindex, yindex)
  149. int xindex, yindex;
  150. {
  151.     int xcoord, ycoord, zcoord;
  152.     zcoord = getdata(xindex, yindex);
  153.     ycoord = scaler(yindex, 10000, xmax);
  154.     xcoord = scaler(xindex, 10000, xmax) - ycoord/2;
  155.     if (conttype == SETUPWATR)
  156.         sealevel(&xcoord, &ycoord, &zcoord);
  157.     plotto(xcoord, ycoord, zcoord);
  158. }
  159.  
  160. sealevel(newx, newy, newz)
  161. int *newx, *newy, *newz;
  162. {
  163.     static int oldx, oldy, oldz;    /* The starting point for the next call. */
  164.     int waterx, watery, waterz;    /* Where the vector hits the waterline. */
  165.     float scratch;
  166.     
  167.     if (linestart) {    /* If at the beginning of the line */
  168.         if ((oldz = *newz) < 0) {        /* and if we're underwater. */
  169.             color = FALSE;
  170.             *newz = 0;        /* Clip to the waterline. */
  171.         }
  172.         else
  173.             color = TRUE;    /* Otherwise we're on land from the start. */
  174.     }
  175.     else {        /* Else we're in the middle of a line and ... */
  176.         if (oldz > 0 && *newz > 0) {    /* start & end points both above water.. */
  177.             oldz = *newz;
  178.         }
  179.         else if (oldz < 0 && *newz < 0) {    /* start & end points both under water... */
  180.             oldz = *newz;
  181.             *newz = 0;        /* Clip at the waterline */
  182.         }
  183.         else {    /* We're now crossing the waterline, */
  184.             /* so calculate the exact point where it dives under. */
  185.             scratch = (float) (*newz)/(*newz-oldz);    /* Proportion of the line that's */
  186.             waterx = (int) ((oldx - *newx)*scratch) + *newx;    /* below the water. */
  187.             watery = (int) ((oldy - *newy)*scratch) + *newy;
  188.             waterz = 0;
  189.  
  190.             plotto(waterx, watery, waterz);        /* Draw to the waterline first. */
  191.             /* The plot from the waterline to the endpoint in the new color 
  192.                is done elsewhere. */
  193.             if (*newz > 0) {    /* Emerging from the water. */
  194.                 color = TRUE;    /* Set new color to 'land'. */
  195.                 oldz = *newz;
  196.             }
  197.             else {        /* Diving into the water. */
  198.                 color = FALSE;    /* Set new color to 'sea'. */
  199.                 oldz = *newz;
  200.                 *newz = 0;
  201.             }
  202.         }
  203.     }
  204.     oldx = *newx;    /* Save the real endpoint of the vector */
  205.     oldy = *newy;    /* to use as the start of the next call. */
  206.             /* (Z taken care of individually above). */
  207. }
  208.  
  209. scaler(base, numer, denom)    /* Computes base*numer/denom with long intermediate.
  210. */
  211. register int base, numer, denom;
  212. {
  213.     register long temp;
  214.     temp = (long) base * (long) numer;
  215.     temp /= (long) denom;
  216.     return (int) temp;
  217. }
  218.  
  219. plotto(x, y, z)        /* Convert 3-D line to a 2-D line and plot it. */
  220. int x, y, z;
  221. {
  222.     rotate(&x, &y);        /* Rotate 30 deg. towards Y in the XY plane */
  223.     tiltdown(&x, &z);    /* Tip 36 deg. down in the ZX plane */
  224.     x /= 25;        /* Scale 10K to 400. */
  225.     y /= 25;
  226.     z /= 25;
  227.     drawline(y, z);        /* Show the YZ planar projection. */
  228. }
  229.  
  230. rotate(x, y)        /* Rotate XY plane 30 deg positive. */
  231. int *x, *y;
  232. {
  233.     cordic(x, y, 5, 17);
  234. }
  235.  
  236. tiltdown(x, z)        /* Rotate XZ plane 36 deg negative (+?). */
  237. int *x, *z;
  238. {
  239.     cordic(x, z, 5, (conttype == SETUPMTN) ? 20 : -20);
  240. }
  241.  
  242. drawline(x, y)        /* Draw either a line from the last endpoint */
  243. int x, y;        /* to the given point, or only a point at x,y. */
  244. {
  245.     static int lastx, lasty;
  246.     x += x/10 + 10;    /* Quick x1.1 + tiny offset. */
  247.     if (conttype == SETUPMTN)
  248.         y = 220 - y;    /* Move the baseline for mountains. */
  249.     else
  250.         y = 80 - y;
  251.     if (linestart || !color)    /* Only a point then. */
  252.         MoveTo(x, y);
  253.     LineTo(x, y);
  254.     lastx = x;
  255.     lasty = y;
  256.     linestart = FALSE;    /* Stuck in the middle with you... */
  257. }
  258.  
  259. cordic(x, y, scale, count)    /* Spin XY vector 'count' steps to the left using */
  260. int *x, *y;            /* CORDIC algorithm with a shift factor of 'scale'. */
  261. register int scale, count;    /* Rotates atan(1/(2^scale)) degrees/step. */
  262.                 /* (Scale of 5 is 1.79 deg/step;  4 = 3.57 d/s...) */
  263.                 /* *x & *y should be large for accuracy. */
  264. {
  265.     register int tempx, tempy;
  266.     tempx = *x;
  267.     tempy = *y;
  268.     if (count>0)    /* Positive count is CCW (left) */
  269.         for (; count; count--) {
  270.             tempx -= (tempy>>scale);
  271.             tempy += (tempx>>scale);
  272.         }
  273.     else        /* Negative is CW (right) */
  274.         for (; count; count++) {
  275.             tempx += (tempy>>scale);
  276.             tempy -= (tempx>>scale);
  277.         }
  278.     *x = tempx;
  279.     *y = tempy;
  280. }
  281.  
  282.